//
//  AKHTTPSURLProtocol.m
//  CertDemo
//
//  Created by chen on 2018/7/6.
//  Copyright © 2018年 chen. All rights reserved.
//

#import "AKHTTPSURLProtocol.h"

static NSString * const URLProtocolHandledKey = @"urlatuh";

@implementation AKHTTPSURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)theRequest
{
    //FIXME: 后来的https类型的reqeust应该也要被处理
    NSString *scheme = [[theRequest URL] scheme];
    if ( ([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
          [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame))
    {
        //看看是否已经处理过了，防止无限循环
        if ([NSURLProtocol propertyForKey:URLProtocolHandledKey inRequest:theRequest]) {
            return NO;
        }
        //此处做个判断,app.xxxx.com是我们项目的域名.任何不属于我们域名的不做处理,这样可以加载https://weibo.com等第三方https网页
        if (![[[theRequest URL] host] isEqualToString:@"admin.96166dache.cn"]) {
            return NO;
        }
        return YES;
    }
    return NO;
}

+ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request
{
    NSMutableURLRequest *mutableReqeust = [request mutableCopy];
    mutableReqeust = [self redirectHostInRequset:mutableReqeust];
    return mutableReqeust;
}

- (void)startLoading
{
    
    
    //theConncetion = [[NSURLConnection alloc] initWithRequest:self.request delegate:self];
    
    NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
    //标示改request已经处理过了，防止无限循环
    [NSURLProtocol setProperty:@YES forKey:URLProtocolHandledKey inRequest:mutableReqeust];
    theConncetion = [NSURLConnection connectionWithRequest:mutableReqeust delegate:self];
    if (theConncetion) {
        _data = [NSMutableData data];
    }
}

- (void)stopLoading
{
    // NOTE:如有清理工作，可以在此处添加
    [theConncetion cancel];
}

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest*)requestA toRequest:(NSURLRequest*)requestB
{
    return [super requestIsCacheEquivalent:requestA toRequest:requestB];
}

#pragma mark - NSURLConnectionDelegate

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    //响应服务器证书认证请求和客户端证书认证请求
    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] ||
    [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    NSURLCredential* credential;
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        //服务器证书认证
        credential= [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
    }
    else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate])
    {
        //客户端证书认证
        //设置客户端证书认证
        
        NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
        NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
        CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
        SecIdentityRef identity;
        // 读取p12证书中的内容
        OSStatus result = [self extractP12Data:inPKCS12Data toIdentity:&identity];
        
        //        if(result != errSecSuccess){
        //            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
        //            return;
        //        }
        
        SecCertificateRef certificate = NULL;
        SecIdentityCopyCertificate(identity, &certificate);
        
        const void *certs[] = {certificate};
        CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
        
        credential = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)CFBridgingRelease(certArray) persistence:NSURLCredentialPersistencePermanent];
    }
    
    if (credential != nil)
    {
        [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
    }
    else
    {
        [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [_data appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [[self client] URLProtocol:self didLoadData:_data];
    [[self client] URLProtocolDidFinishLoading:self];
    
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    [[self client] URLProtocol:self didFailWithError:error];
    
}
- (OSStatus)extractP12Data:(CFDataRef)inP12Data toIdentity:(SecIdentityRef *)identity {
    OSStatus securityErr = errSecSuccess;
    
    CFStringRef pwd = CFSTR("123456");
    const void *keys[] = {kSecImportExportPassphrase};
    const void *values[] = {pwd};
    
    CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    securityErr = SecPKCS12Import(inP12Data, options, &items);
    
    if (securityErr == errSecSuccess) {
        CFDictionaryRef ident = CFArrayGetValueAtIndex(items, 0);
        const void *tmpIdent = NULL;
        tmpIdent = CFDictionaryGetValue(ident, kSecImportItemIdentity);
        *identity = (SecIdentityRef)tmpIdent;
    }
    
    if (options) {
        CFRelease(options);
    }
    
    return securityErr;
}
+(NSMutableURLRequest*)redirectHostInRequset:(NSMutableURLRequest*)request
{
    if ([request.URL host].length == 0) {
        return request;
    }
    
    NSString *originUrlString = [request.URL absoluteString];
    NSLog(@"-----链接导向---------->:%@",originUrlString);
    
    NSString *originHostString = [request.URL host];
    NSRange hostRange = [originUrlString rangeOfString:originHostString];
    if (hostRange.location == NSNotFound) {
        return request;
    }
    //此处可以将网页中链接的域名替换为自己的域名,防止劫持.
    //    NSString *ip = @"app.xxxx.com";
    //     // 替换域名
    //    NSString *urlString;
    //    if ([originUrlString isEqualToString:@"apis.map.qq.com"]) {
    //        urlString=originUrlString;
    //    }else if ([originUrlString isEqualToString:@"weibo.com"]){
    //        urlString=originUrlString;
    //
    //    }else{
    //        urlString = [originUrlString stringByReplacingCharactersInRange:hostRange withString:ip];
    //    }
    
    //    NSURL *url = [NSURL URLWithString:originUrlString];
    //    request.URL = url;
    
    return request;
}

@end
